﻿using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NTLib.Pipe.Providers;
using NTLib.Pipe.Targets;
using System.Threading.Tasks;
using NTLib.Pipe.UTest.TestData;
using NTLib.Core.Tasks;
using NTLib.Pipe.Containers;
using NTLib.Core.Threading;
using NTLib.Pipe.Descriptors;

namespace NTLib.Pipe.UTest.Providers
{
    /// <summary>
    /// Description résumée pour MemoryProvidersUTest
    /// </summary>
    [TestClass]
    public class MemoryPipeProvidersUTest
    {
        #region Method

        [TestCategory("Pipe.Memory.Provider")]
        [TestMethod]
        public void MemoryPipeProvider_CreateAndGetSimple()
        {
            var prov = new MemoryProvider();
            var guid = Guid.NewGuid();
            DataStruct data = new DataStruct();
            data.Data = guid.ToString();
            using (var pipe = prov.CreateAsync<DataStruct>(PipeType.TwoWay, LocalTargetDescription.Instance).WaitResult())
            {
                Assert.IsInstanceOfType(pipe, typeof(IPipeManipulatorOwner<DataStruct>));
                Assert.IsInstanceOfType(pipe, typeof(TwoWayPipeOwner<DataStruct>));

                pipe.SendAsync(data).Wait();

                using (var twowaypipe = prov.GetPipeAsync<DataStruct>(pipe.Id).WaitResult())
                {

                    Assert.IsInstanceOfType(twowaypipe, typeof(IPipeManipulator<DataStruct>));
                    Assert.IsInstanceOfType(twowaypipe, typeof(TwoWayPipe<DataStruct>));


                    var dataRead = twowaypipe.PopAsync().WaitResult();

                    Assert.AreNotEqual(dataRead, null);
                    Assert.AreEqual(data.Data, dataRead.Data);

                    data = new DataStruct();
                    data.Data = Guid.NewGuid().ToString();
                    twowaypipe.SendAsync(data).Wait();

                    dataRead = pipe.PopAsync().WaitResult();

                    Assert.AreNotEqual(dataRead, null);
                    Assert.AreEqual(data.Data, dataRead.Data);
                }
            }
        }

        [TestCategory("Pipe.Memory.Provider")]
        [TestMethod]
        public void MemoryPipeProvider_CreateAndGetSimpleOneWay()
        {
            var prov = new MemoryProvider();
            var guid = Guid.NewGuid();
            DataStruct data = new DataStruct();
            data.Data = guid.ToString();
            using (var pipe = prov.CreateAsync<DataStruct>(PipeType.OneWay, LocalTargetDescription.Instance).WaitResult())
            {
                Assert.IsInstanceOfType(pipe, typeof(IPipeManipulatorOwner<DataStruct>));
                Assert.IsInstanceOfType(pipe, typeof(PushOnlyPipeOwner<DataStruct>));

                pipe.SendAsync(data).Wait();

                using (var readPipe = prov.GetPipeAsync<DataStruct>(pipe.Id).WaitResult())
                {
                    Assert.AreNotEqual(readPipe, null);
                    Assert.IsInstanceOfType(readPipe, typeof(IPipeManipulator<DataStruct>));
                    Assert.IsInstanceOfType(readPipe, typeof(ReadOnlyPipe<DataStruct>));

                    var dataRead = readPipe.PopAsync().WaitResult();

                    Assert.AreNotEqual(dataRead, null);
                    Assert.AreEqual(data.Data, dataRead.Data);
                }
            }
        }

        [TestCategory("Pipe.Memory.Provider")]
        [TestMethod]
        public void MemoryPipeProvider_CreateAndGetSimpleFromTarget()
        {
            var prov = new MemoryProvider();
            var guid = Guid.NewGuid();
            DataStruct data = new DataStruct();
            data.Data = guid.ToString();
            using (var pipe = prov.CreateAsync<DataStruct>(PipeType.FromTarget, LocalTargetDescription.Instance).WaitResult())
            {
                Assert.IsInstanceOfType(pipe, typeof(IPipeManipulatorOwner<DataStruct>));
                Assert.IsInstanceOfType(pipe, typeof(ReadOnlyPipeOwner<DataStruct>));

                using (var sendPipe = prov.GetPipeAsync<DataStruct>(pipe.Id).WaitResult())
                {

                    Assert.IsInstanceOfType(sendPipe, typeof(IPipeManipulator<DataStruct>));
                    Assert.IsInstanceOfType(sendPipe, typeof(PushOnlyPipe<DataStruct>));

                    sendPipe.SendAsync(data).Wait();

                    var dataRead = pipe.PopAsync().WaitResult();

                    Assert.AreNotEqual(dataRead, null);
                    Assert.AreEqual(data.Data, dataRead.Data);
                }
            }
        }

        [TestCategory("Pipe.Memory.Provider")]
        [TestMethod]
        public void MemoryPipeProvider_CanGet()
        {
            var prov = new MemoryProvider();

            using (var pipe = prov.CreateAsync<DataStruct>(PipeType.TwoWay, LocalTargetDescription.Instance).WaitResult())
            {
                Assert.IsTrue(prov.CanGetPipeAsync(pipe.Id).WaitResult());
            }

            using (var pipe = prov.CreateAsync<DataStruct>(PipeType.FromTarget, LocalTargetDescription.Instance).WaitResult())
            {
                Assert.IsTrue(prov.CanGetPipeAsync(pipe.Id).WaitResult());
            }

            using (var pipe = prov.CreateAsync<DataStruct>(PipeType.OneWay, LocalTargetDescription.Instance).WaitResult())
            {
                Assert.IsTrue(prov.CanGetPipeAsync(pipe.Id).WaitResult());
            }
        }

        #endregion endregion
    }
}
